#!/usr/bin/env python

# Uses the patched 'pygooglevoice' library. This will not work with the
# unpatched version. Go here to see the patch and a short discussion
# about it:
#
#   http://code.google.com/p/pygooglevoice/issues/detail?id=22#c12
#
# This also needs the BeautifulSoup XML parsing package. I tested this
# with the following version of that library:
#
#   http://www.crummy.com/software/BeautifulSoup/download/3.x/BeautifulSoup-3.0.8.1.tar.gz

from googlevoice import Voice
import re
import sys
import BeautifulSoup

from time import mktime,strptime
from datetime import datetime,timedelta

def nextConversation(json, html) :
    tree = BeautifulSoup.BeautifulSoup(html)
    convBlock = tree.findAll('div', attrs={'id' : True}, recursive=False)
    jsonMessages = json['messages']
    for conv in convBlock :
        convId = conv['id']
        convmap = jsonMessages[convId]
        rows = conv.findAll(attrs={'class' : 'gc-message-sms-row'})
        messages = []
        for row in rows:
            spans = row.findAll('span', attrs={'class' : True}, recursive=False)
            msgitem = {}
            for span in spans:
                cl = span['class'].replace('gc-message-sms-', '')
                msgitem[cl] = (' '.join(span.findAll(text=True))).strip()
            messages.append(msgitem)
        convmap['messages'] = messages
        yield convmap
    return

voice = Voice()
voice.login()

conversations = []
page = 0
while True:
    page += 1
    voice.sms(page)
    
    count = 0
    for conv in nextConversation(voice.sms.data, voice.sms.html):
        count += 1
        conversations.insert(0, conv)
    if count < 1:
        break
    print 'page %d' % page


## As a proof of concept, just print out the data structures for the
## earliest and latest conversation. You can iterate over the
## 'conversations' list to get the data for all of the conversations.

print len(conversations)
print '\n%s\n\n%s' % (repr(conversations[0]), repr(conversations[-1]))

import json

for conversation in conversations:
    last = None
    for message in reversed(conversation['messages']):
        # use actual month day and year instead of 2000
        time = datetime.fromtimestamp(mktime(strptime(message['time']+" 2000", "%I:%M %p %Y")))
        if not last:
            last = time
        offset = last - time
        if offset.days * 86400 + offset.seconds < 0:
            offset += timedelta(days=1)
        message['messageTime'] = (datetime.fromtimestamp(int(conversation['startTime'])/1000) - offset).isoformat()

print json.dumps(conversations[0],sort_keys=True, indent=4)
print json.dumps(conversations[-1],sort_keys=True, indent=4)
print json.dumps(conversations[-2],sort_keys=True, indent=4)
